package org.sample.commons.ftp;

import java.io.*;

import org.apache.commons.net.ftp.FTPClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 本类实现FTP文件基础操作功能
 * 非线程安全
 */
public class FTPClientImpl extends AbstractFTPClient {

    private static final Logger log = LoggerFactory.getLogger(FTPClientImpl.class);

    private FTPClient ftpClient;

    public FTPClientImpl(FTPConfig config) throws FTPException {
        super(config);
    }

    /**
     * 连接到服务器
     */
    @Override
    public void connect() throws FTPException {
        if (ftpClient == null)
            ftpClient = new FTPClient();
        try {
            log.debug("FTP start");
            ftpClient.connect(config.getHost(), config.getPort());
            ftpClient.login(config.getUsername(), config.getPassword());
            ftpClient.setDataTimeout(config.getTimeout());
            log.debug("FTP login SUCCESS");
        } catch (Exception e) {
            throw new FTPException("连接FTP服务器失败", e);
        }
    }

    /**
     * 关闭FTP连接
     */
    @Override
    public void disconnect() {
        log.debug("FTP disconnect");
        if (ftpClient == null)
            return;
        try {
            ftpClient.logout();
        } catch (Exception e) {
            log.warn("FTP注销失败", e);
        }
        try {
            ftpClient.disconnect();
        } catch (Exception e) {
            log.warn("FTP关闭连接失败", e);
        }
    }

    @Override
    public void mkdir(String path) throws FTPException {
        try {
            ftpClient.mkd(path);
        } catch (IOException e) {
            throw new FTPException("创建目录失败", e);
        }
    }

    /**
     * 切换到指定的FTP目录
     */
    @Override
    public void changeDir(String directory) throws FTPException {
        try {
            if (!ftpClient.changeWorkingDirectory(directory)) {
                ftpClient.mkd(directory);
                exception(ftpClient.changeWorkingDirectory(directory));
            }
        } catch (Exception e) {
            throw new FTPException("切换目录失败", e);
        }
    }

    @Override
    public void upload(File file, String fileName) throws FTPException {
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(file));
            exception(ftpClient.storeFile(fileName, bis));
        } catch (Exception e) {
            throw new FTPException("上传文件失败", e);
        } finally {
            close(bis);
        }
    }

    @Override
    public void upload(byte[] bytes, String fileName) throws FTPException {
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new ByteArrayInputStream(bytes));
            exception(ftpClient.storeFile(fileName, bis));
        } catch (Exception e) {
            throw new FTPException("上传文件失败", e);
        } finally {
            close(bis);
        }
    }

    @Override
    public File download(String ftpFileName, String localFileName) throws FTPException {
        File file = new File(localFileName);
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(file));
            exception(ftpClient.retrieveFile(ftpFileName, bos));
            bos.flush();
            return file;
        } catch (Exception e) {
            file.delete();
            throw new FTPException("下载文件失败", e);
        } finally {
            close(bos);
        }
    }

    @Override
    public void download(String ftpFileName, File localFile) throws FTPException {
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(localFile));
            exception(ftpClient.retrieveFile(ftpFileName, bos));
            bos.flush();
        } catch (Exception e) {
            throw new FTPException("下载文件失败", e);
        } finally {
            close(bos);
        }
    }

    @Override
    public void delete(String filename) throws FTPException {
        try {
            exception(ftpClient.deleteFile(filename));
        } catch (Exception e) {
            throw new FTPException("删除文件失败", e);
        }
    }

    @Override
    public void rename(String oldFileName, String newFileName) throws FTPException {
        try {
            exception(ftpClient.rename(oldFileName, newFileName));
        } catch (Exception e) {
            throw new FTPException("重命名FTP服务器文件名错误");
        }
    }

    private static void exception(boolean bool) throws Exception {
        if (!bool)
            throw new Exception("operation failed,FTP Server return false!");
    }

    private static void close(Closeable... streams) {
        for (Closeable stream : streams)
            if (stream != null)
                try {
                    stream.close();
                } catch (Exception e) {
                }
    }

}